package Game.Online.Messages 
{
	import Box2D.Common.Math.b2Vec2;
	import Common.Input;
	import Common.Utils;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import Game.GameElements.GameObject;
	import Game.GameElements.Tank;
	import Game.Online.Messages.Message;
	import Game.Online.OnlineManager;
	import Game.Windows.MessageWindow;
	/**
	 * ...
	 * @author Yevgeniy Logachev
	 */
	public class MessagesHandler 
	{
		private static const 	s_instance:MessagesHandler 	= new MessagesHandler();
		private static var 		m_pendingMessages:Vector.<Message> = new Vector.<Message>();
		
		public function MessagesHandler() 
		{
			if (s_instance == null)
			{
				trace ("MessagesHandler initialized");
			}
			else
			{
				trace("ERROR: Already existing instance in Singleton");
				throw new Error("Already existing instance in Singleton");
			}
		}
		
		public static function get instance():MessagesHandler
		{
			return s_instance;
		}
		
		public function createMessage(data:ByteArray, isReceived:Boolean = false):void
		{
			data.endian = Endian.LITTLE_ENDIAN;
			
			data.position = 0;
			try
			{
				var type:int = data.readInt();
				var id:String = data.readUTF();
				
				if (!OnlineManager.instance.isLoggedIn && type != MessagesDefs.k_MESSAGE_LOGIN && type != MessagesDefs.k_MESSAGE_DOUBLE_LOGIN)
				{
					return;
				}
			}
			catch (e:Error)
			{
				trace("ERROR: message null");
				return;
			}
			
			var msg:Message;
			
			switch(type)
			{
				case MessagesDefs.k_MESSAGE_LOGIN:
					msg = new MessageLogIn(id);
					(msg as MessageLogIn).setData(data.readUTF(), data.readInt(), data.readDouble(), data.readDouble());
				break;
				
				case MessagesDefs.k_MESSAGE_CORRECT_POSITION:
					msg = new MessageCorrectPosition(id);
					(msg as MessageCorrectPosition).setData(data.readDouble(), data.readDouble(), data.readInt());
				break;
				
				case MessagesDefs.k_MESSAGE_KEY_PRESS:
					msg = new MessageKeyPress(id);
					(msg as MessageKeyPress).setData(data.readInt());
				break;
				
				case MessagesDefs.k_MESSAGE_DO_ROCKET:
					msg = new MessageDoRocket(id);
					(msg as MessageDoRocket).setData(data.readInt());
				break;
				
				case MessagesDefs.k_MESSAGE_DOUBLE_LOGIN:
					msg = new MessageDoubleLogIn(id);
				break;
				
				case MessagesDefs.k_MESSAGE_UNLOGIN:
					msg = new Message(MessagesDefs.k_MESSAGE_UNLOGIN, id);
				break;
				
				default:
				break;
			}
			
			msg.isReceived = isReceived;
			addMessage(msg);
		}
		
		public function addMessage(msg:Message):void
		{
			m_pendingMessages.push(msg);
		}
		
		public static function update():void
		{
			while (m_pendingMessages.length > 0)
			{
				for each(var msg:Message in m_pendingMessages)
				{
					if (msg.isReceived)
					{	
						switch(msg.type)
						{
							case MessagesDefs.k_MESSAGE_LOGIN:
								OnlineManager.instance.onLogIn(msg as MessageLogIn);
							break;
							
							case MessagesDefs.k_MESSAGE_CORRECT_POSITION:
								updatePositionsRemotePlayers(msg as MessageCorrectPosition);
							break;
							
							case MessagesDefs.k_MESSAGE_KEY_PRESS:
								messageKeyPress(msg as MessageKeyPress);
							break;
							
							case MessagesDefs.k_MESSAGE_DO_ROCKET:
								OnlineManager.instance.doRocket(msg as MessageDoRocket);
							break;
							
							case MessagesDefs.k_MESSAGE_DOUBLE_LOGIN:
								new MessageWindow("Error", "Вы уже играете из другого места", "Ok", "Cancel");
								Main.startMenu();
							break;
							
							case MessagesDefs.k_MESSAGE_UNLOGIN:
								playerUnlogin(msg);
							break;
						}
					}
					else
					{
						OnlineManager.instance.connection.sendMessage(msg);
					}
					
					m_pendingMessages.splice(m_pendingMessages.indexOf(msg), 1);
				}
			}
		}
		
		public static function messageKeyPress(msg:MessageKeyPress):void
		{
			if (msg.id != OnlineManager.instance.connection.id)
			{
				for each(var gameObject:GameObject in GameObject.gameObjects)
				{
					if (gameObject is Tank && msg.id == (gameObject as Tank).m_remoteId)
					{
						var keyCode:int = msg.keyCode;
						if (keyCode == Input.KEY_RIGHT)
						{
							(gameObject as Tank).moveTo(Tank.DIRECTION_RIGHT);
						}
						else if (keyCode == Input.KEY_LEFT)
						{
							(gameObject as Tank).moveTo(Tank.DIRECTION_LEFT);
						}
						else if (keyCode == Input.KEY_DOWN)
						{
							(gameObject as Tank).moveTo(Tank.DIRECTION_DOWN);
						}
						else if (keyCode == Input.KEY_UP)
						{
							(gameObject as Tank).moveTo(Tank.DIRECTION_UP);
						}
						
						if (keyCode == Input.KEY_SPACE)
						{
							(gameObject as Tank).doRocket();
						}
					}
				}
			}				
		}
		
		public static function updatePositionsRemotePlayers(msg:MessageCorrectPosition):void
		{
			if (msg.id != OnlineManager.instance.connection.id)
			{
				for each(var gameObject:GameObject in GameObject.gameObjects)
				{
					if (gameObject is Tank &&msg.id == (gameObject as Tank).m_remoteId)
					{
						if (gameObject.physicalObject != null)
						{
							gameObject.physicalObject.SetPosition(msg.position);
							(gameObject as Tank).setDirection = msg.rotation;
						}
					}
				}
			}
		}
		
		public static function playerUnlogin(msg:Message):void
		{
			if (msg.id != OnlineManager.instance.connection.id)
			{
				for each(var gameObject:GameObject in GameObject.gameObjects)
				{
					if (gameObject is Tank)
					{
						if (msg.id == (gameObject as Tank).m_remoteId)
						{
							GameObject.gameObjects.splice(GameObject.gameObjects.indexOf(gameObject), 1);
							gameObject.release();
							gameObject = null;
						}
					}
				}
			}
		}
	}

}